iT邦幫忙

1

前端面試必考題: Promise

  • 分享至 

  • xImage
  •  

這篇文章會是參考這篇文章,並且濃縮出重點,最後也會有幾題測驗,方便驗收學習狀況,那麼我們進入今天的文章: Promise

什麼是 Promise?

Promise 通常會由 「生產者代碼」(producing code) 跟 「消費者代碼」(consuming code) 組成

生產者代碼 (producing code)

通過網路加載數據的程式碼,例如: 餐廳

消費者代碼 (consuming code)

想要在"生產者代碼"完成工作的第一時間就能獲得其工作成果的程式碼,例如: 顧客


生產者代碼 - Promise 對象的構造器 (constructor)

let promise = new Promise(function(resolve, reject) {
  // executor
});

傳遞給 new Promise 的函數被稱為 executorexecutor 會在 new Promise 被創立時,自動執行

這邊可以看到有 resolvereject 兩個參數,分別代表成功或失敗

  • resolve(value)
  • reject(error)

new Promise 除了會有 result (resolve 或是 reject),還有 state ,代表該 Promise 的執行狀態

預設會是 pending ,resolve 被調用時變為 fulfilled,或者在 reject 被調用時變為 rejected

任何一個 resolvedrejected 的 promise 都會被稱為 settled

這只能有一個結果或一個 error

let promise = new Promise(function(resolve, reject) {
  resolve("done");

  reject(new Error("…")); // 被忽略
  setTimeout(() => resolve("…")); // 被忽略
});

這邊想說明的是不管是 resolve 還是 reject,任何一個被觸發後,就會跳脫出 Promise,所以後面的 resolve 或是 reject,就會被省略掉

state 和 result 都是内部的

剛剛有提到的 state 和 result 都只存活在該 Promise 中,一但離開了 Promise ,將不復存在,不過我們可以透過 .then().catch() 去接收 result


消費者代碼

.then()

p.then(onFulfilled, onRejected);

.then() 接受兩個參數,分別是 Promise 在成功及失敗情況時的回呼函式。

let promise = new Promise(function(resolve, reject) {
  setTimeout(() => resolve("done!"), 1000);
});

promise.then(
  result => alert(result),
  error => alert(error)
);

.catch()

.catch() 只會抓取 錯誤 (reject) 的 result

如果只對於錯誤 result 有興趣,有兩種方法

p.then(null, errorHandlingFunction) // 將 onFulfilled 設定為 null

p..catch(errorHandlingFunction)

.finally()

finally 的功能是設置一個處理程式在前面的操作完成後,執行清理/終結。
finally 的執行時間是在 promise settled 時就會執行:無論 promise 的result 是 resolve 還是 reject。


小試身手

這邊分享四題我覺得還不錯的考題,給各位讀者做練習

  1. 請說明 console 出來的順序
const promise = new Promise((resolve, reject) => {
    console.log(1)
    resolve()
    console.log(2)
})
promise.then(() => {
    console.log(3)
})
console.log(4)

答案:

1 -> 2 -> 4 -> 3

原因是因為 Promise 構造函數是同步執行的,promise.then 中的函數是異步執行的

  1. 請說明 console 出來的順序,這題比較常,不過感覺會是業界會考的題目
const first = () => (new Promise((resolve, reject) => {
    console.log(3);
    let p = new Promise((resolve, reject) => {
        console.log(7);
        setTimeout(() => {
            console.log(5);
            resolve(6);
        }, 0)
        resolve(1);
    });
    resolve(2);
    p.then((arg) => {
        console.log(arg);
    });

}));

first().then((arg) => {
    console.log(arg);
});
console.log(4);

答案:

3 -> 7 -> 4 -> 1 -> 2 -> 5

相信大家基本上都能答出 3 -> 7 -> 4 ,至於後面的 1 -> 2 -> 5 是因為 setTimeout 是一個 Macrotask 他會先被放到 task queue 中,等待 Microtask 都執行完成才會被丟到 call stack 中執行
如果不清楚 macrotask 跟 microtask 的讀者,可以參考我之前的文章

  1. 請問下方程式碼會 console 出什麼東西?
const promise = new Promise((resolve, reject) => {
  resolve('success1')
  reject('error')
  resolve('success2')
})

promise
  .then((res) => {
    console.log('then: ', res)
  })
  .catch((err) => {
    console.log('catch: ', err)
  })

答案:

then: success1

原因是因為 Promise 中的 resolve 或 reject 只有第一次執行有效,所以後面的都會被省略
4. 請問下方程式碼會 console 出什麼?

Promise.resolve(1)
  .then((res) => {
    console.log(res)
    return 2
  })
  .catch((err) => {
    return 3
  })
  .then((res) => {
    console.log(res)
  })

答案:

1 2

原因是因為 Promise 可以鏈式調用。
Promise 每次調用 .then 或者 .catch 都會返回一個新的 Promise,從而實現了鏈式調用。
至於不是 1 3 的原因是因為是 resolve
可以想像成

Promise.resolve(1)
  .then((res) => {
    console.log(res)
    return 2
  })

Promise.resolve(2)
  .then((res) => {
    console.log(res)
  })

以上就是今天 Promise 的介紹,文章最後還是推薦各位讀者可以去看看JavaScript.info 的文章

文章同步發佈在我的 Medium ,有興趣的讀者可以去看看

以上就是今天的文章,如果有任何錯誤,或是問題都歡迎留言給我,那我們下次見,掰掰

參考文章:
https://javascript.info/promise-basics

https://medium.com/@123davidbill/macrotask-vs-microtask-%E5%B8%B8%E6%90%9E%E9%8C%AF%E7%9A%84%E9%83%A8%E5%88%86-236b7c2b8e8b


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言